package com.oliet.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.oliet.common.dto.permission.CreatePermissionDTO;
import com.oliet.common.dto.permission.UpdatePermissionDTO;
import com.oliet.common.vo.page.PageVO;
import com.oliet.common.vo.permission.PermissionTreeNodeVO;
import com.oliet.common.vo.permission.PermissionVO;
import com.oliet.entity.Permissions;
import com.oliet.entity.RolePermissions;
import com.oliet.entity.Roles;
import com.oliet.entity.base.BaseEntity;
import com.oliet.exception.CustomException;
import com.oliet.exception.ErrorEnum;
import com.oliet.mapper.PermissionsMapper;
import com.oliet.mapper.RolePermissionsMapper;
import com.oliet.mapper.RolesMapper;
import com.oliet.service.PermissionsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.oliet.util.CodeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author JZP
 * @since 2023-11-26
 */
@Service
public class PermissionsServiceImpl extends ServiceImpl<PermissionsMapper, Permissions> implements PermissionsService {

    @Autowired
    private RolesMapper rolesMapper;
    @Autowired
    private RolePermissionsMapper rolePermissionsMapper;

    @Override
    public void create(CreatePermissionDTO param) {
        long count = this.count(new LambdaQueryWrapper<Permissions>()
                .eq(Permissions::getPermissionName, param.getPermissionName())
                .eq(Permissions::getParentId, param.getParentId() == null ? 0L : param.getParentId()));
        if (count > 0) {
            throw new CustomException(ErrorEnum.PERMISSION_NAME_EXIST);
        }
        Permissions po = new Permissions();
        BeanUtil.copyProperties(param, po);
        po.setCode(CodeUtils.getCommonCode());
        if (param.getParentId() == null) {
            //顶层菜单父权限ID为0，层级为1
            po.setParentId(0L);
            po.setLevel(1);
        } else {
            //校验父权限是否存在
            Permissions parent = this.getById(param.getParentId());
            Assert.notNull(parent, () -> new CustomException(ErrorEnum.PARENT_PERMISSION_NOT_EXIST));
            po.setLevel(parent.getLevel() + 1);
        }
        this.save(po);
    }

    @Override
    public PageVO<PermissionVO> pageList(Long pageNo, Long pageSize, String search) {
        //分页查询
        Page<Permissions> page = new Page<>(pageNo, pageSize);
        Page<Permissions> poData = this.page(page, new LambdaQueryWrapper<Permissions>()
                .and(
                        StrUtil.isNotBlank(search),
                        wrapper -> wrapper.like(Permissions::getPermissionName, search)
                                .or()
                                .like(Permissions::getDescription, search)
                ).orderByDesc(BaseEntity::getDateCreated)
        );
        List<PermissionVO> voList = PermissionVO.poListConverVoList(poData.getRecords());
        PageVO<PermissionVO> pageVo = new PageVO<>(poData.getCurrent(), poData.getSize(), poData.getTotal(), voList);
        return pageVo;
    }

    @Override
    public PermissionVO info(Long id) {
        Permissions po = this.getById(id);
        return PermissionVO.poConverVo(po);
    }

    @Override
    public List<PermissionTreeNodeVO> tree() {
        List<Permissions> list = this.list();
        List<PermissionTreeNodeVO> treeList = PermissionTreeNodeVO.buildTree(list);
        return treeList;
    }

    @Override
    public List<PermissionTreeNodeVO> getByRole(Long roleId) {
        Roles roles = this.rolesMapper.selectById(roleId);
        if (ObjectUtil.isNull(roles)) {
            throw new CustomException(ErrorEnum.ROLE_DOES_NOT_EXIST);
        }
        List<RolePermissions> rolePermissions = this.rolePermissionsMapper.selectList(new LambdaQueryWrapper<RolePermissions>().eq(RolePermissions::getRoleId, roleId));
        if (CollectionUtil.isEmpty(rolePermissions)) {
            throw new CustomException(ErrorEnum.ROLE_PERMISSION_NOT_EXIST);
        }
        List<Long> idList = rolePermissions.stream().map(RolePermissions::getPermissionId).collect(Collectors.toList());
        List<Permissions> list = this.list(new LambdaQueryWrapper<Permissions>().in(BaseEntity::getId, idList));
        List<PermissionTreeNodeVO> treeList = PermissionTreeNodeVO.buildTree(list);
        return treeList;
    }

    @Override
    public void deleteById(Long id) {
        Permissions po = this.getOne(new LambdaQueryWrapper<Permissions>()
                .eq(BaseEntity::getId, id));
        if (ObjectUtil.isNull(po)) {
            throw new CustomException(ErrorEnum.PERMISSION_DOES_NOT_EXIST);
        }
        List<Permissions> list = this.list(new LambdaQueryWrapper<Permissions>()
                .eq(Permissions::getParentId, po.getId()));
        if (CollectionUtil.isNotEmpty(list)) {
            String errorMsg = list.stream().map(Permissions::getPermissionName)
                    .collect(Collectors.joining(", "));
            throw new CustomException(ErrorEnum.PERMISSION_EXIST_SUB, errorMsg);
        }
        this.removeById(id);
    }

    @Override
    public void update(UpdatePermissionDTO param) {
        //查询权限
        Permissions po = this.getById(param.getId());
        Assert.notNull(po, () -> new CustomException(ErrorEnum.PERMISSION_DOES_NOT_EXIST));
        //校验权限名称
        Permissions one = this.getOne(new LambdaQueryWrapper<Permissions>()
                .eq(Permissions::getPermissionName, param.getPermissionName())
                .eq(Permissions::getParentId, po.getParentId()));
        if (ObjectUtil.isNotNull(one) && !po.getId().equals(one.getId())) {
            throw new CustomException(ErrorEnum.ROLE_NAME_EXIST);
        }
        //修改权限数据
        BeanUtil.copyProperties(param, po, "id");
        this.updateById(po);
    }
}
